<!DOCTYPE html>





<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 3.9.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=7.4.0">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=7.4.0">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=7.4.0">
  <link rel="mask-icon" href="/images/logo.svg?v=7.4.0" color="#222">

<link rel="stylesheet" href="/css/main.css?v=7.4.0">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css?v=4.7.0">


<script id="hexo-configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    version: '7.4.0',
    exturl: false,
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":false},
    copycode: {"enable":true,"show_result":false,"style":null},
    back2top: {"enable":true,"sidebar":false,"scrollpercent":true},
    bookmark: {"enable":false,"color":"#222","save":"auto"},
    fancybox: false,
    mediumzoom: false,
    lazyload: false,
    pangu: false,
    algolia: {
      appID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    },
    localsearch: {"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},
    path: 'search.xml',
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    translation: {
      copy_button: '复制',
      copy_success: '复制成功',
      copy_failure: '复制失败'
    },
    sidebarPadding: 40
  };
</script>

  <meta name="description" content="[toc]纯手工实现线性回归（作业一）​    近年来机器学习和深度学习十分火热，应用十分广泛。在完成本科毕设过程中和在信工所实习的时候深感自己对于深度学习方面的知识掌握的远远不够，因此打算在暑假期间恶补一下深度学习。寻找学习资料的时候，在B站发现了一个宝藏教程, 台大李宏毅教授对于深度学习中的各种技术和算法讲解的十分透彻，并且公开了作业，甚至有些作业是以kaggle比赛的形式，我们也可以提交自己">
<meta name="keywords" content="Python,李宏毅深度学习2020">
<meta property="og:type" content="article">
<meta property="og:title" content="纯手工实现线性回归（作业一）">
<meta property="og:url" content="http://yoursite.com/2020/07/06/2020-07-06-纯手工实现线性回归（作业一）/index.html">
<meta property="og:site_name" content="SunPages">
<meta property="og:description" content="[toc]纯手工实现线性回归（作业一）​    近年来机器学习和深度学习十分火热，应用十分广泛。在完成本科毕设过程中和在信工所实习的时候深感自己对于深度学习方面的知识掌握的远远不够，因此打算在暑假期间恶补一下深度学习。寻找学习资料的时候，在B站发现了一个宝藏教程, 台大李宏毅教授对于深度学习中的各种技术和算法讲解的十分透彻，并且公开了作业，甚至有些作业是以kaggle比赛的形式，我们也可以提交自己">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200706230448.png">
<meta property="og:image" content="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200706232114.png">
<meta property="og:image" content="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200710233546.png">
<meta property="og:image" content="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200711001312.png">
<meta property="og:image" content="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200711004430.png">
<meta property="og:image" content="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200711005519.png">
<meta property="og:updated_time" content="2020-07-10T16:57:02.917Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="纯手工实现线性回归（作业一）">
<meta name="twitter:description" content="[toc]纯手工实现线性回归（作业一）​    近年来机器学习和深度学习十分火热，应用十分广泛。在完成本科毕设过程中和在信工所实习的时候深感自己对于深度学习方面的知识掌握的远远不够，因此打算在暑假期间恶补一下深度学习。寻找学习资料的时候，在B站发现了一个宝藏教程, 台大李宏毅教授对于深度学习中的各种技术和算法讲解的十分透彻，并且公开了作业，甚至有些作业是以kaggle比赛的形式，我们也可以提交自己">
<meta name="twitter:image" content="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200706230448.png">
  <link rel="canonical" href="http://yoursite.com/2020/07/06/2020-07-06-纯手工实现线性回归（作业一）/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: false,
    isPost: true,
    isPage: false,
    isArchive: false
  };
</script>

  <title>纯手工实现线性回归（作业一） | SunPages</title>
  








  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .logo,
  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">
  <div class="container use-motion">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">SunPages</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <h1 class="site-subtitle" itemprop="description">屁话少说,放码过来！</h1>
      
  </div>

  <div class="site-nav-toggle">
    <button aria-label="切换导航栏">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
      
      
      
        
        <li class="menu-item menu-item-home">
      
    

    <a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i> <br>首页</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-about">
      
    

    <a href="/about/" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i> <br>关于</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-tags">
      
    

    <a href="/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i> <br>标签</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-categories">
      
    

    <a href="/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i> <br>分类</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-archives">
      
    

    <a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i> <br>归档</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-photos">
      
    

    <a href="/photo/" rel="section"><i class="menu-item-icon fa fa-fw fa-image"></i> <br>Photos</a>

  </li>
      <li class="menu-item menu-item-search">
        <a href="javascript:;" class="popup-trigger">
        
          <i class="menu-item-icon fa fa-search fa-fw"></i> <br>搜索</a>
      </li>
    
  </ul>

</nav>
  <div class="site-search">
    <div class="popup search-popup">
    <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input" id="search-input"></div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="algolia-results">
  <div id="algolia-stats"></div>
  <div id="algolia-hits"></div>
  <div id="algolia-pagination" class="algolia-pagination"></div>
</div>

  
</div>
<div class="search-pop-overlay"></div>

  </div>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/sunhanwu" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
            

          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
      <article itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block post">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2020/07/06/2020-07-06-纯手工实现线性回归（作业一）/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="sunhanwu">
      <meta itemprop="description" content="Talk is cheap, show me the code!">
      <meta itemprop="image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-09-12-logo.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="SunPages">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">纯手工实现线性回归（作业一）

          
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              
                
              

              <time title="创建时间：2020-07-06 00:00:00" itemprop="dateCreated datePublished" datetime="2020-07-06T00:00:00+08:00">2020-07-06</time>
            </span>
          
            

            
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-07-11 00:57:02" itemprop="dateModified" datetime="2020-07-11T00:57:02+08:00">2020-07-11</time>
              </span>
            
          
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/深度学习/" itemprop="url" rel="index"><span itemprop="name">深度学习</span></a></span>

                
                
              
            </span>
          

          
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="fa fa-comment-o"></i>
      </span>
        
      
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/2020/07/06/2020-07-06-纯手工实现线性回归（作业一）/#comments" itemprop="discussionUrl"><span class="post-comments-count valine-comment-count" data-xid="/2020/07/06/2020-07-06-纯手工实现线性回归（作业一）/" itemprop="commentCount"></span></a>
  </span>
  
  
          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
              
                <span class="post-meta-item-text">本文字数：</span>
              
              <span>5.9k</span>
            </span>
          
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="fa fa-clock-o"></i>
              </span>
              
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              
              <span>5 分钟</span>
            </span>
          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>[toc]</p><h1 id="纯手工实现线性回归（作业一）"><a href="#纯手工实现线性回归（作业一）" class="headerlink" title="纯手工实现线性回归（作业一）"></a>纯手工实现线性回归（作业一）</h1><p>​    近年来机器学习和深度学习十分火热，应用十分广泛。在完成本科毕设过程中和在信工所实习的时候深感自己对于深度学习方面的知识掌握的远远不够，因此打算在暑假期间恶补一下深度学习。寻找学习资料的时候，在B站发现了一个<a href="https://www.bilibili.com/video/BV1JE411g7XF?p=1" target="_blank" rel="noopener">宝藏教程</a>, 台大李宏毅教授对于深度学习中的各种技术和算法讲解的十分透彻，并且公开了作业，甚至有些作业是以kaggle比赛的形式，我们也可以提交自己写的作业。因此打算跟随教程完成这些作业，并且将每次的作业报告发布到自己的博客，主要是方便以后自己查阅。</p><a id="more"></a>

<p>​    这篇博客是作业一，kaggle比赛的<a href="https://www.kaggle.com/c/ml2020spring-hw1" target="_blank" rel="noopener">传送门</a>在此,kaggle平台上有作业提供的数据集合介绍。助教也给做了相关的<a href="https://docs.google.com/presentation/d/18MG1wSTTx8AentGnMfIRUp8ipo8bLpgAj16bJoqW-b0/edit#slide=id.g4cd6560e29_0_42" target="_blank" rel="noopener">说明</a></p>
<p>​    我个人在<a href="https://github.com/sunhanwu/dl2020" target="_blank" rel="noopener">github仓库</a>，完整的数据和代码里面都有</p>
<h2 id="准备数据"><a href="#准备数据" class="headerlink" title="准备数据"></a>准备数据</h2><h3 id="数据集介绍"><a href="#数据集介绍" class="headerlink" title="数据集介绍"></a>数据集介绍</h3><p>数据集的详细介绍在kaggle平台上都有，助教提供的ppt和视频说明中也都有。这里简单介绍一下我认为值得关注的几个点。</p>
<ul>
<li><p>题目要求根据前9个小时的数据预测第10个小时的PM2.5的数值。因此对于每个样本来说前9个小时内所有观测数据都属于特征值，特征值共包括18种观测指标，每种观测指标9个数据，所以一个样本的特征值个数为$18 * 9 = 162$, 而PM2.5在第十个小时的数值作为label</p>
</li>
<li><p>一天24个小时，按照1的方式进行提取样本的话可以提取15个样本数据</p>
</li>
<li><p>数据中存在NR值的话需要给替换为数值0</p>
</li>
</ul>
<p><img src="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200706230448.png" alt></p>
<h3 id="数据预处理"><a href="#数据预处理" class="headerlink" title="数据预处理"></a>数据预处理</h3><p>基本了解了数据集合题目要求之后，就需要对数据进行预处理工作了，首先处理训练数据。</p>
<h3 id="处理训练数据"><a href="#处理训练数据" class="headerlink" title="处理训练数据"></a>处理训练数据</h3><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">loadTrainData</span><span class="params">(trainDataFile)</span>:</span></span><br><span class="line">    <span class="string">"""</span></span><br><span class="line"><span class="string">    加载训练数据集，并且处理成需要的格式</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line">    trainData = pd.read_csv(trainDataFile, encoding=<span class="string">'big5'</span>)</span><br><span class="line">    <span class="comment"># 去除日期等误用数据</span></span><br><span class="line">    trainData = trainData.iloc[:, <span class="number">2</span>:]</span><br><span class="line">    <span class="comment"># 将NR替换为0,并将其转回为numpy</span></span><br><span class="line">    trainData[trainData == <span class="string">'NR'</span>] = <span class="number">0</span></span><br><span class="line">    <span class="comment"># 原始的数据大小为4320*25</span></span><br><span class="line">    trainDataArray = trainData.to_numpy().astype(<span class="string">'float64'</span>)</span><br><span class="line">    <span class="comment"># 重组数据</span></span><br><span class="line">    rows, columns = trainDataArray.shape</span><br><span class="line">    Data = []</span><br><span class="line">    <span class="keyword">for</span> day <span class="keyword">in</span> range(rows // <span class="number">18</span>):</span><br><span class="line">        rowLow = day * <span class="number">18</span></span><br><span class="line">        rowHigh = rowLow + <span class="number">18</span></span><br><span class="line">        rowPM25 = rowLow + <span class="number">9</span></span><br><span class="line">        <span class="keyword">for</span> columnLeft <span class="keyword">in</span> range(<span class="number">15</span>):</span><br><span class="line">            columnRight = columnLeft + <span class="number">9</span></span><br><span class="line">            OneTrainData = trainDataArray[rowLow:rowHigh, columnLeft:columnRight].reshape(<span class="number">-1</span>)</span><br><span class="line">            label = trainDataArray[rowPM25, columnRight]</span><br><span class="line">            oneSampleData = np.append(OneTrainData, label)</span><br><span class="line">            Data.append(oneSampleData)</span><br><span class="line">    Data = np.array(Data)</span><br><span class="line">    <span class="keyword">return</span> Data[:, :<span class="number">162</span>], Data[:, <span class="number">162</span>]</span><br></pre></td></tr></tbody></table></figure>
<ul>
<li>原始数据文件中，每天的数据有18个观测指标，每个观测指标记录24个数值，共有240天的数据。因此原始数据集（去除日期和指标名称等误用信息）对应的大小为4320*24</li>
<li>一个样本对应同一天中18中观测指标中连续9个小时的观测数据，特征值个数为18*9=162，df的shape为(18,9)</li>
<li>label为同一天连续9个小时观测数据后一小时的pm2.5数值</li>
<li>使用pandas按照上述方法截取到对应位置的数值后将其reshape为一维数据，得到(162,1)的数据，加上label值后维度为(163,1)</li>
</ul>
<p><img src="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200706232114.png" style="zoom:50%;"></p>
<h3 id="处理测试数据"><a href="#处理测试数据" class="headerlink" title="处理测试数据"></a>处理测试数据</h3><p>测试数据和训练数据的处理方式类似，只是过程简单一些。测试数据是给出每天前9个小时各个观测指标的数值，要求我们预测每天第10个小时的PM2.5值</p>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">loadTestData</span><span class="params">(testDataFile)</span>:</span></span><br><span class="line">    <span class="string">"""</span></span><br><span class="line"><span class="string">    加载测试数据</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line">    testData = pd.read_csv(testDataFile, encoding=<span class="string">'big5'</span>, header=<span class="literal">None</span>)</span><br><span class="line">    testData = testData.iloc[:, <span class="number">2</span>:]</span><br><span class="line">    testData[testData == <span class="string">'NR'</span>] = <span class="number">0</span></span><br><span class="line">    testDataArray = testData.to_numpy()</span><br><span class="line">    rows, column = testDataArray.shape</span><br><span class="line">    Data = []</span><br><span class="line">    <span class="keyword">for</span> day <span class="keyword">in</span> range(rows // <span class="number">18</span>):</span><br><span class="line">        rowLow = day * <span class="number">18</span></span><br><span class="line">        rowHigh = rowLow + <span class="number">18</span></span><br><span class="line">        OneTestData = testDataArray[rowLow:rowHigh, :].reshape(<span class="number">-1</span>)</span><br><span class="line">        Data.append(OneTestData)</span><br><span class="line">    Data = np.array(Data)</span><br><span class="line">    <span class="keyword">return</span> Data</span><br></pre></td></tr></tbody></table></figure>
<h3 id="数据归一化"><a href="#数据归一化" class="headerlink" title="数据归一化"></a>数据归一化</h3><p>由于不同特征表示的是空气质量的不同指标，其值域范围有很大的不同，这样的训练数据会很严重的影响模型的性能，至于是如何影响可以看下面模型调优里面关于数据归一化的相关介绍</p>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">normalization</span><span class="params">(data)</span>:</span></span><br><span class="line">    mu = np.mean(data, axis=<span class="number">0</span>)</span><br><span class="line">    sigma = np.std(data, axis=<span class="number">0</span>)</span><br><span class="line">    result = (data - mu) / sigma</span><br><span class="line">    result =  np.nan_to_num(result)</span><br><span class="line">    <span class="keyword">return</span> result</span><br></pre></td></tr></tbody></table></figure>
<p>我简单的将各个特征的极差(最大值和最小值)绘制成如下的图像：</p>
<p><img src="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200710233546.png" style="zoom:50%;"></p>
<ul>
<li>可以看到不同特征之间的极差相差特别大，这种变化会导致后来梯度下降过程中出现一些问题，某些特征对应的wight的梯度变化的比其他的块的多，有可能导致出现梯度爆炸等情况。</li>
<li>使用归一化函数后这种数据之间的极差不平衡就会消失</li>
</ul>
<h2 id="定义模型"><a href="#定义模型" class="headerlink" title="定义模型"></a>定义模型</h2><h3 id="定义dataLoader"><a href="#定义dataLoader" class="headerlink" title="定义dataLoader"></a>定义dataLoader</h3><p>首先定义一个数据装载器，并于对数据进行shuffle操作，每次返回batch_size数据便于后续进行随机梯度下降。</p>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">dataIter</span><span class="params">(batchSize, feature, label, shuffle=True)</span>:</span></span><br><span class="line">    <span class="string">"""</span></span><br><span class="line"><span class="string">    将训练数据进行shuffle，按照一个batch_size的数据量返回</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line">    numExample = len(feature)</span><br><span class="line">    indexs = list(range(numExample))</span><br><span class="line">    <span class="keyword">if</span> shuffle:</span><br><span class="line">        random.shuffle(indexs)</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">0</span>, numExample, batchSize):</span><br><span class="line">        index = indexs[i:i + batchSize]</span><br><span class="line">        <span class="keyword">yield</span> feature[index], label[index]</span><br></pre></td></tr></tbody></table></figure>
<h3 id="定义线性回归模型和损失函数"><a href="#定义线性回归模型和损失函数" class="headerlink" title="定义线性回归模型和损失函数"></a>定义线性回归模型和损失函数</h3><ol>
<li>定义线性回归模型</li>
</ol>
<p>线性回归是最简单的机器学习模型，对于每个特征值都有一个对应的参数w，模型中对应的参数$w_i$乘以$x_i$求和后加上bias，具体的公示如下：</p>
<script type="math/tex; mode=display">
\hat y_i = \sum {w_i* x_i} + b_i</script><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">regression</span><span class="params">(feature, param)</span>:</span></span><br><span class="line">    predict = np.dot(feature, param[<span class="number">0</span>]) + param[<span class="number">1</span>]</span><br><span class="line">    <span class="keyword">return</span> predict</span><br></pre></td></tr></tbody></table></figure>
<p>​    需要注意的是在具体计算的时候feature不是简单的一个向量，而是由多个向量组成的一个矩阵，对应变量维度信息如下：</p>
<script type="math/tex; mode=display">
w = param[0]\\
b = param[1]\\
dim(feature) = (batch\_size, num\_feature)\\
dim(param[0]) = (num\_feature, 1)\\
dim(b) = 1\\
dim(\hat y) = (batch\_size, 1)</script><ol>
<li>定义损失函数</li>
</ol>
<p>损失函数就是最普通的平方损失函数，就是直接计算模型预测的值$\hat y$和真实的$y$的差的值的平方的平均值。为了在求导过程中方便计算，一般有人多除以个2，也有人不除。下面是损失函数的公示：</p>
<script type="math/tex; mode=display">
Loss = \frac {1}{N} (y_i - (w_i x_i + b))^2</script><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">Loss</span><span class="params">(predict, label)</span>:</span></span><br><span class="line">    <span class="keyword">return</span> np.sum((label - predict) ** <span class="number">2</span>) / (<span class="number">2</span> *len(label))</span><br></pre></td></tr></tbody></table></figure>
<p>这里的predict和label都是长度为batch_size的向量</p>
<h3 id="定义随机梯度下降函数MBGD"><a href="#定义随机梯度下降函数MBGD" class="headerlink" title="定义随机梯度下降函数MBGD"></a>定义随机梯度下降函数MBGD</h3><p>梯度下降算法是整个机器学习里面最为核心的算法。可以说整个无论是复杂的LSTM，CNN等深度学习网络，还是简单的线性回归/逻辑回归都是靠着各种各样的梯度下降算法来实现对参数的更新，从而实现让模型更加智能的目的。下面首先介绍SGD的实现过程，如果在后续实验过程中发现效果不好的话则换用其他梯度下降算法。</p>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">算法名</th>
<th style="text-align:center">说明</th>
<th style="text-align:center">优缺点</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">BGD</td>
<td style="text-align:center">采用整个训练集的数据来计算 cost function 对参数的梯度</td>
<td style="text-align:center">由于这种方法是在一次更新中，就对整个数据集计算梯度，所以计算起来非常慢，遇到很大量的数据集也会非常棘手，而且不能投入新数据实时更新模型</td>
</tr>
<tr>
<td style="text-align:center">SGD</td>
<td style="text-align:center">每次更新时对每个样本进行梯度更新</td>
<td style="text-align:center">对于很大的数据集来说，可能会有相似的样本，这样 BGD 在计算梯度时会出现冗余，而 SGD 一次只进行一次更新，就没有冗余，而且比较快，并且可以新增样本。<br>SGD 因为更新比较频繁，会造成 cost function 有严重的震荡。BGD 可以收敛到局部极小值，当然 SGD 的震荡可能会跳到更好的局部极小值处。</td>
</tr>
<tr>
<td style="text-align:center">MBGD</td>
<td style="text-align:center">MBGD 每一次利用一小批样本，即 n 个样本进行计算</td>
<td style="text-align:center">这样它可以降低参数更新时的方差，收敛更稳定，另一方面可以充分地利用深度学习库中高度优化的矩阵操作来进行更有效的梯度计算<br>不过 Mini-batch gradient descent 不能保证很好的收敛性，learning rate 如果选择的太小，收敛速度会很慢，如果太大，loss function 就会在极小值处不停地震荡甚至偏离。<br></td>
</tr>
</tbody>
</table>
</div>
<p>在梯度下降算法中最为重要的是对损失函数进行求导，下面给出线性回归模型中对于w和b的求导公示（因为线性回归模型比较简单，手工求导不复杂，但是之后复杂的神经网络中一般使用深度学习框架进行自动求导）</p>
<script type="math/tex; mode=display">
\frac{\partial L o s s}{\partial m}=\frac{\frac{1}{N} \sum_{i=1}^{N}\left(y_{i}-\left(m x_{i}+b\right)\right)^{2}}{\partial m}=-\frac{2}{N} \sum_{i=1}^{N} x_{i}\left(y_{i}-\left(m x_{i}+b\right)\right)\\
\frac{\partial L o s s}{\partial b}=\frac{\frac{1}{N} \sum_{i=1}^{N}\left(y_{i}-\left(m x_{i}+b\right)\right)^{2}}{\partial b}=-\frac{2}{N} \sum_{i=1}^{N}\left(y_{i}-\left(m x_{i}+b\right)\right)</script><p>下面是对应的python代码实现</p>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">MBGD</span><span class="params">(param, lr, features, labels)</span>:</span></span><br><span class="line">    <span class="string">"""</span></span><br><span class="line"><span class="string">    使用SGD优化器</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line">    w = param[<span class="number">0</span>]</span><br><span class="line">    b = param[<span class="number">1</span>]</span><br><span class="line">    N = len(labels)</span><br><span class="line">    h = np.dot(features, w) + b</span><br><span class="line">    labels = labels.reshape(h.shape)</span><br><span class="line">    dw = features.T.dot((h - labels)) / N</span><br><span class="line">    db = np.sum((h - labels)) / N</span><br><span class="line">    new_w = w - lr * dw</span><br><span class="line">    new_b = b - lr * db</span><br><span class="line">    new_param = (new_w, new_b)</span><br><span class="line">    <span class="keyword">return</span> new_param</span><br></pre></td></tr></tbody></table></figure>
<ul>
<li>注意这里对参数w和b的求导方式和上面所述公示结果是一致的，只是将$\hat y$放在了前面而已</li>
</ul>
<h2 id="模型调优"><a href="#模型调优" class="headerlink" title="模型调优"></a>模型调优</h2><p>​    经过上述一系列的准备工作，已经能够跑起来一个简单的线性回归模型，下面是经过上面模型跑出来的loss曲线图, 模型在训练集和验证集上都能够有效的训练，并且没有出现过拟合现象。</p>
<p><img src="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200711001312.png" style="zoom:50%;"></p>
<p>将预测得到的实验结果应用到测试数据集上得到结果, 并提交到kaggle上进行测试，发现自己写了个<span class="github-emoji" style="color: transparent;background:no-repeat url(https://github.githubassets.com/images/icons/emoji/unicode/1f4a9.png?v8) center/contain" data-src="https://github.githubassets.com/images/icons/emoji/unicode/1f4a9.png?v8">💩</span>，baseline的score是8.7377, 注意这里的score是越底越好</p>
<p><img src="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200711004430.png" style="zoom:50%;"></p>
<p>所以必须对上述的模型进行调优</p>
<h3 id="欠拟合"><a href="#欠拟合" class="headerlink" title="欠拟合"></a>欠拟合</h3><p>从上面的loss曲线图可以看出来，loss曲线还在下降中，并没有收敛。因此可以尝试增大epoch，增大训练的轮数，直到最后完全收敛。</p>
<p>最后当epoch设置为1000的时候看到loss曲线有明显得到收敛。</p>
<p><img src="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200711005519.png" style="zoom:50%;"></p>
<h2 id="未完待续"><a href="#未完待续" class="headerlink" title="未完待续"></a>未完待续</h2><script>
        document.querySelectorAll('.github-emoji')
          .forEach(el => {
            if (!el.dataset.src) { return; }
            const img = document.createElement('img');
            img.style = 'display:none !important;';
            img.src = el.dataset.src;
            img.addEventListener('error', () => {
              img.remove();
              el.style.color = 'inherit';
              el.style.backgroundImage = 'none';
              el.style.background = 'none';
            });
            img.addEventListener('load', () => {
              img.remove();
            });
            document.body.appendChild(img);
          });
      </script>
    </div>

    
    
    
        
      
        <div id="reward-container">
  <div></div>
  <button id="reward-button" disable="enable" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';">
    打赏
  </button>
  <div id="qr" style="display: none;">
        
      
      <div style="display: inline-block">
        <img src="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200705000845.png" alt="sunhanwu 支付宝">
        <p>支付宝</p>
      </div>

  </div>
</div>

      

      <footer class="post-footer">
          
            
          
          <div class="post-tags">
            
              <a href="/tags/Python/" rel="tag"># Python</a>
            
              <a href="/tags/李宏毅深度学习2020/" rel="tag"># 李宏毅深度学习2020</a>
            
          </div>
        

        

          <div class="post-nav">
            <div class="post-nav-next post-nav-item">
              
                <a href="/2020/07/04/2020-07-04-Pandas玩转数据透视表/" rel="next" title="Pandas玩转数据透视表">
                  <i class="fa fa-chevron-left"></i> Pandas玩转数据透视表
                </a>
              
            </div>

            <span class="post-nav-divider"></span>

            <div class="post-nav-prev post-nav-item">
              
            </div>
          </div>
        
      </footer>
    
  </div>
  
  
  
  </article>

  </div>


          </div>
          
    
    <div class="comments" id="comments"></div>
  

        </div>
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">
        
        
        
        
      

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#纯手工实现线性回归（作业一）"><span class="nav-number">1.</span> <span class="nav-text">纯手工实现线性回归（作业一）</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#准备数据"><span class="nav-number">1.1.</span> <span class="nav-text">准备数据</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#数据集介绍"><span class="nav-number">1.1.1.</span> <span class="nav-text">数据集介绍</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#数据预处理"><span class="nav-number">1.1.2.</span> <span class="nav-text">数据预处理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#处理训练数据"><span class="nav-number">1.1.3.</span> <span class="nav-text">处理训练数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#处理测试数据"><span class="nav-number">1.1.4.</span> <span class="nav-text">处理测试数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#数据归一化"><span class="nav-number">1.1.5.</span> <span class="nav-text">数据归一化</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#定义模型"><span class="nav-number">1.2.</span> <span class="nav-text">定义模型</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#定义dataLoader"><span class="nav-number">1.2.1.</span> <span class="nav-text">定义dataLoader</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#定义线性回归模型和损失函数"><span class="nav-number">1.2.2.</span> <span class="nav-text">定义线性回归模型和损失函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#定义随机梯度下降函数MBGD"><span class="nav-number">1.2.3.</span> <span class="nav-text">定义随机梯度下降函数MBGD</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#模型调优"><span class="nav-number">1.3.</span> <span class="nav-text">模型调优</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#欠拟合"><span class="nav-number">1.3.1.</span> <span class="nav-text">欠拟合</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#未完待续"><span class="nav-number">1.4.</span> <span class="nav-text">未完待续</span></a></li></ol></li></ol></div>
        
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image"
      src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-09-12-logo.jpg"
      alt="sunhanwu">
  <p class="site-author-name" itemprop="name">sunhanwu</p>
  <div class="site-description" itemprop="description">Talk is cheap, show me the code!</div>
</div>
  <nav class="site-state motion-element">
      <div class="site-state-item site-state-posts">
        
          <a href="/archives/">
        
          <span class="site-state-item-count">28</span>
          <span class="site-state-item-name">博客</span>
        </a>
      </div>
    
      
      
      <div class="site-state-item site-state-categories">
        
          
            <a href="/categories/">
          
        
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span>
        </a>
      </div>
    
      
      
      <div class="site-state-item site-state-tags">
        
          
            <a href="/tags/">
          
        
        <span class="site-state-item-count">18</span>
        <span class="site-state-item-name">标签</span>
        </a>
      </div>
    
  </nav>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
      
      
        
      
      
        
      
        <a href="https://github.com/sunhanwu" title="GitHub &rarr; https://github.com/sunhanwu" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
    
      <span class="links-of-author-item">
      
      
        
      
      
        
      
        <a href="mailto:1965190613@qq.com" title="E-Mail &rarr; mailto:1965190613@qq.com" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
    
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title">
      <i class="fa fa-fw fa-link"></i>
      Links
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://jackyanghc.github.io/" title="https://jackyanghc.github.io/" rel="noopener" target="_blank">Jackyanghc</a>
        </li>
      
        <li class="links-of-blogroll-item">
          <a href="https://michel-liu.github.io/" title="https://michel-liu.github.io/" rel="noopener" target="_blank">Michel</a>
        </li>
      
        <li class="links-of-blogroll-item">
          <a href="https://www.cnblogs.com/morwing/" title="https://www.cnblogs.com/morwing/" rel="noopener" target="_blank">morwing</a>
        </li>
      
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">sunhanwu</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    
    <span title="站点总字数">158k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span class="post-meta-item-text">站点阅读时长 &asymp;</span>
    
    <span title="站点阅读时长">2:24</span>
</div>
  <div class="theme-info">主题 – <a href="https://theme-next.org" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> v7.4.0</div>

        












        
      </div>
    </footer>
  </div>

  


  <script src="/lib/anime.min.js?v=3.1.0"></script>
  <script src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  <script src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
<script src="/js/utils.js?v=7.4.0"></script><script src="/js/motion.js?v=7.4.0"></script>
<script src="/js/schemes/pisces.js?v=7.4.0"></script>
<script src="/js/next-boot.js?v=7.4.0"></script>



  
  <script>
    (function(){
      var bp = document.createElement('script');
      var curProtocol = window.location.protocol.split(':')[0];
      bp.src = (curProtocol === 'https') ? 'https://zz.bdstatic.com/linksubmit/push.js' : 'http://push.zhanzhang.baidu.com/push.js';
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
    })();
  </script>








  
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/instantsearch.js@2/dist/instantsearch.min.css">
<script src="//cdn.jsdelivr.net/npm/instantsearch.js@2/dist/instantsearch.min.js"></script><script src="/js/algolia-search.js?v=7.4.0"></script>















  

  
    
      
<script type="text/x-mathjax-config">

  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$', '$'], ['\\(', '\\)'] ],
      processEscapes: true,
      skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
    },
    TeX: {
      equationNumbers: {
        autoNumber: 'AMS'
      }
    }
  });

  MathJax.Hub.Register.StartupHook('TeX Jax Ready', function() {
    MathJax.InputJax.TeX.prefilterHooks.Add(function(data) {
      if (data.display) {
        var next = data.script.nextSibling;
        while (next && next.nodeName.toLowerCase() === '#text') {
          next = next.nextSibling;
        }
        if (next && next.nodeName.toLowerCase() === 'br') {
          next.parentNode.removeChild(next);
        }
      }
    });
  });

  MathJax.Hub.Queue(function() {
    var all = MathJax.Hub.getAllJax(), i;
    for (i = 0; i < all.length; i += 1) {
      element = document.getElementById(all[i].inputID + '-Frame').parentNode;
      if (element.nodeName.toLowerCase() == 'li') {
        element = element.parentNode;
      }
      element.classList.add('has-jax');
    }
  });
</script>
<script>
  NexT.utils.getScript('//cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML', () => {
    MathJax.Hub.Typeset();
  }, window.MathJax);
</script>

    
  

  

  


<script>
NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
  var GUEST = ['nick', 'mail', 'link'];
  var guest = 'nick,mail,link';
  guest = guest.split(',').filter(item => {
    return GUEST.includes(item);
  });
  new Valine({
    el: '#comments',
    verify: false,
    notify: false,
    appId: 'ToSqcWxrMe4Fx1bTFKjHnFQn-gzGzoHsz',
    appKey: 'WIlMiWIudPsl2Q2PsMVfiUUH',
    placeholder: 'Just go go',
    avatar: 'mm',
    meta: guest,
    pageSize: '10' || 10,
    visitor: false,
    lang: '' || 'zh-cn',
    path: location.pathname
  });
}, window.Valine);
</script>

</body>
</html>
